package com.xbts.system.module.payment.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xbts.common.constant.UserConstants;
import com.xbts.common.core.domain.CnWalletLog;
import com.xbts.common.core.domain.entity.SysUser;
import com.xbts.common.core.domain.model.LoginUser;
import com.xbts.common.enums.ShoppingCarEnums;
import com.xbts.common.exception.ServiceException;
import com.xbts.common.utils.DateUtils;
import com.xbts.common.utils.QueryWrapperUtil;
import com.xbts.common.utils.SecurityUtils;
import com.xbts.common.utils.StringUtils;
import com.xbts.system.domain.CnOrderItem;
import com.xbts.system.mapper.SysUserMapper;
import com.xbts.system.module.payment.enums.PaymentMethodEnum;
import com.xbts.system.module.payment.mapper.CnWalletLogMapper;
import com.xbts.system.module.payment.service.ICnWalletLogService;
import com.xbts.system.service.ICnCloudMarketService;
import com.xbts.system.service.ICnCloudMarketSkuService;
import com.xbts.system.service.ICnGovernmentCloudService;
import com.xbts.system.service.ICnOrderItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 用户钱包日志Service业务层处理
 *
 * @author xbts
 * @date 2023-08-04
 */
@Service("CnWalletLogServiceImpl")
public class CnWalletLogServiceImpl extends ServiceImpl<CnWalletLogMapper, CnWalletLog> implements ICnWalletLogService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ICnOrderItemService orderItemService;

    @Autowired
    private ICnGovernmentCloudService cnGovernmentCloudService;

    @Autowired
    private ICnCloudMarketSkuService cnCloudMarketSkuService;

    @Autowired
    private ICnCloudMarketService cnCloudMarketService;


    /**
     * 查询用户钱包日志列表
     *
     * @param cnWalletLog 用户钱包日志
     * @return 用户钱包日志
     */
    @Override
    public List<CnWalletLog> selectCnWalletLogList(CnWalletLog cnWalletLog) {
        QueryWrapper<CnWalletLog> queryWrapper = QueryWrapperUtil.getQueryWrapper(cnWalletLog);
        genSelect (cnWalletLog,  queryWrapper);
        List<CnWalletLog> list = list(queryWrapper);
        for (CnWalletLog walletLog : list) {
            if(StringUtils.isBlank(walletLog.getTerm())) {
                String term = "";
                List<CnOrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<CnOrderItem>()
                        .eq(CnOrderItem::getSn, walletLog.getSn()));
                for (CnOrderItem orderItem : orderItems) {
                    term = StringUtils.isBlank(term) ? "" + orderItem.getOrderAbstract() : "\n" + orderItem.getOrderAbstract();
                }
                walletLog.setTerm(term);
            }
        }
        return list;
    }

    /**
     * 构建查询条件
     * @param cnWalletLog 用户钱包日志
     * @param queryWrapper 查询条件
     */
    private void genSelect (CnWalletLog cnWalletLog, QueryWrapper<CnWalletLog> queryWrapper) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 用户名称模糊查询
        if (StringUtils.isNotBlank(cnWalletLog.getNickName())) {
            queryWrapper.like("nick_name", cnWalletLog.getNickName());
        }
        // 用户名称模糊查询
        if (StringUtils.isNotNull(cnWalletLog.getShoppingCarEnums())) {
            queryWrapper.eq("shopping_car_enums", cnWalletLog.getShoppingCarEnums());
        }
        if(StringUtils.isNotBlank(cnWalletLog.getPaymentMethod()) && PaymentMethodEnum.REFUND.name().equals(cnWalletLog.getPaymentMethod())) {// 查询退款
            queryWrapper.eq("payment_method", PaymentMethodEnum.REFUND.name());
        }
        // 充值查询
        else if (StringUtils.isNotBlank(cnWalletLog.getPaymentMethod()) && !PaymentMethodEnum.WALLET.name().equals(cnWalletLog.getPaymentMethod())) {
            queryWrapper.ne("payment_method", PaymentMethodEnum.WALLET.name());
            queryWrapper.ne("payment_method", PaymentMethodEnum.REFUND.name());
            queryWrapper.ne("payment_method", PaymentMethodEnum.PLATFORM_DECREASE.name());

            queryWrapper.and(v -> {
                v.ne("payment_method", PaymentMethodEnum.ACCOUNT.name())
                        .or().eq("shopping_car_enums", ShoppingCarEnums.RECHARGE.name());
            });
        } else if(StringUtils.isNotBlank(cnWalletLog.getPaymentMethod()) && PaymentMethodEnum.WALLET.name().equals(cnWalletLog.getPaymentMethod())) {// 余额查询
            queryWrapper.and(v -> {
                v.eq("payment_method", PaymentMethodEnum.WALLET.name());
                v.or().eq("payment_method", PaymentMethodEnum.REFUND.name());
                v.or().eq("payment_method", PaymentMethodEnum.PLATFORM_DECREASE.name());
                v.or(c -> {
                    c.and(m -> {
                        m.eq("payment_method", PaymentMethodEnum.ACCOUNT.name())
                                .and(n -> n.ne("shopping_car_enums", ShoppingCarEnums.RECHARGE.name()));
                    });
                });
            });
        }
        if (StringUtils.isNotNull(cnWalletLog.getParams())) {
        if (StringUtils.isNotNull(cnWalletLog.getParams().get("startTime")) && StringUtils.isNotBlank(cnWalletLog.getParams().get("startTime") + "")) {
            queryWrapper.ge("create_time", cnWalletLog.getParams().get("startTime"));
        }
        if (StringUtils.isNotNull(cnWalletLog.getParams().get("endTime")) && StringUtils.isNotBlank(cnWalletLog.getParams().get("endTime") + "")) {
            queryWrapper.le("create_time", cnWalletLog.getParams().get("endTime"));
        }
        }
        // 非管理人员
        if (!loginUser.getUser().getUserType().equals(UserConstants.USER_TYPE_MANAGER)) {
            queryWrapper.eq("user_id", loginUser.getUserId());
        }
        queryWrapper.orderByDesc("create_time");
    }

    /**
     * 查询用户钱包日志
     *
     * @param id 用户钱包日志主键
     * @return 用户钱包日志
     */
    @Override
    public CnWalletLog selectCnWalletLogById(String id) {
        return getById(id);
    }

    /**
     * 新增用户钱包日志
     *
     * @param cnWalletLog 用户钱包日志
     * @return 结果
     */
    @Override
    public boolean insertCnWalletLog(CnWalletLog cnWalletLog) {
        cnWalletLog.setCreateBy(SecurityUtils.getUserId().toString());
        return save(cnWalletLog);
    }

    /**
     * 修改用户钱包日志
     *
     * @param cnWalletLog 用户钱包日志
     * @return 结果
     */
    @Override
    public boolean updateCnWalletLog(CnWalletLog cnWalletLog) {
        cnWalletLog.setUpdateBy(SecurityUtils.getUserId().toString());
        cnWalletLog.setUpdateTime(DateUtils.getNowDate());
        return updateById(cnWalletLog);
    }

    /**
     * 批量删除用户钱包日志
     *
     * @param ids 需要删除的用户钱包日志主键
     * @return 结果
     */
    @Override
    public boolean deleteCnWalletLogByIds(List<String> ids) {
        return removeBatchByIds(ids);
    }

    /**
     * 删除用户钱包日志信息
     *
     * @param id 用户钱包日志主键
     * @return 结果
     */
    @Transactional
    @Override
    public boolean deleteCnWalletLogById(String id) {
        return removeById(id);
    }

    /**
     * 更新用户余额
     *  @param userId        用户id
     * @param price         余额
     * @param paymentMethod 支付方式
     * @param receivableNo  第三方流水号
     * @param shoppingCarEnums
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void updateUserBalanceAndLog(long userId, BigDecimal price, String paymentMethod, String receivableNo, ShoppingCarEnums shoppingCarEnums, String sn, String isAutoRenew) {
        // 查询用户余额
        SysUser sysUser = userMapper.selectUserById(userId);

        BigDecimal userWallet = sysUser.getUserWallet();
        BigDecimal balance = BigDecimal.ZERO;
        if(!paymentMethod.equals(PaymentMethodEnum.ACCOUNT.name()) || shoppingCarEnums.equals(ShoppingCarEnums.RECHARGE)) {
            // 计算余额
            balance = userWallet.add(price);
            if (balance.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("余额不足！");
            }
            baseMapper.updateUserBalance(userId, balance);
        }

        // 查询消费金额 //余额支付的
        QueryWrapper<CnWalletLog> walletLogLambdaQueryWrapper = new QueryWrapper<>();
        walletLogLambdaQueryWrapper.select("IFNULL(sum(money),0) as money");
        walletLogLambdaQueryWrapper.eq("user_id", userId);
        walletLogLambdaQueryWrapper.eq("payment_method", PaymentMethodEnum.WALLET.name());
        CnWalletLog dbWalletLog = getOne(walletLogLambdaQueryWrapper);
        // 记录日志
        CnWalletLog cnWalletLog = new CnWalletLog();
        if (dbWalletLog != null) {
            cnWalletLog.setConsumptionAmount(dbWalletLog.getMoney());
        }
        if (StringUtils.isNotNull(shoppingCarEnums)){
            cnWalletLog.setShoppingCarEnums(shoppingCarEnums);
        }
        if (StringUtils.isNotEmpty(sn)){
            cnWalletLog.setSn(sn);
        }
        cnWalletLog.setPaymentMethod(paymentMethod);
        cnWalletLog.setUserId(userId);
        cnWalletLog.setMoney(price);
        cnWalletLog.setNickName(sysUser.getNickName());
        cnWalletLog.setBalance(balance);
        cnWalletLog.setCreateBy("1");
        cnWalletLog.setAutoRenew(isAutoRenew);
        if (StringUtils.isNotEmpty(receivableNo)) {
            cnWalletLog.setReceivableNo(receivableNo);
        }
        save(cnWalletLog);
    }

    @Override
    public JSONObject statisticsWalletLogList(CnWalletLog cnWalletLog) {
        QueryWrapper<CnWalletLog> queryWrapper;
        String paymentMethod = cnWalletLog.getPaymentMethod();

        queryWrapper = QueryWrapperUtil.getQueryWrapper(cnWalletLog);
        queryWrapper.select("count(1) order_count");
        genSelect (cnWalletLog,  queryWrapper);
        CnWalletLog allCount = getOne(queryWrapper);

        queryWrapper = QueryWrapperUtil.getQueryWrapper(cnWalletLog);
        queryWrapper.select("count(1) order_count");
        cnWalletLog.setPaymentMethod(PaymentMethodEnum.REFUND.name());
        genSelect (cnWalletLog,  queryWrapper);
        CnWalletLog refund = getOne(queryWrapper);
        if(!PaymentMethodEnum.WALLET.name().equals(paymentMethod)){
            refund.setOrderCount(0);
        }

        queryWrapper = QueryWrapperUtil.getQueryWrapper(cnWalletLog);
        queryWrapper.select("ifnull(sum(money), 0) money");
        cnWalletLog.setPaymentMethod("OTHER");
        genSelect (cnWalletLog,  queryWrapper);
        CnWalletLog all = getOne(queryWrapper);

        queryWrapper = QueryWrapperUtil.getQueryWrapper(cnWalletLog);
        queryWrapper.select("ifnull(sum(money), 0) money");
        cnWalletLog.setPaymentMethod(PaymentMethodEnum.WALLET.name());
        genSelect (cnWalletLog,  queryWrapper);
        CnWalletLog consumption = getOne(queryWrapper);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("all", all.getMoney());
        jsonObject.put("consumption", consumption.getMoney().abs());
        jsonObject.put("orderCount", allCount.getOrderCount() - (refund.getOrderCount() * 2));
        return jsonObject;
    }

}
